<!--表格设置工具栏，放在表格组件之外,一般在AntTable组件使用@tableLoadingReady="(tableThis)=>{this.$refs.antTableSettingTool.showButtons(tableThis)}将表格与此工具栏关联"-->
<template>
  <div class="c-params" v-if="tableShowSetting&&visible">
    <ant-button
        iconEnable
        title="Excel导出"
        v-if="excelDownLoad"
        type="default"
        icon="download"
        @click="exportExcel"
    ></ant-button>
    <ant-button
        iconEnable
        title="Excel导出"
        v-if="excelDownLoadSelected"
        type="default"
        icon="download"
        @click="exportExcelSelected"
    ></ant-button>
    <!--表格属性-->
    <a-dropdown :visible="tableVisible.attrVisible">
      <ant-button iconEnable title="表格属性" icon="appstore" type="default" @click="()=>{this.tableVisible.attrVisible=true}"></ant-button>
      <div slot="overlay" class="c-params-attr" @mouseleave="()=>{this.tableVisible.attrVisible=false}">
        <div class="c-params-attr-row">
          <div class="c-params-attr-row-col" v-for="(item,indexRow) in getTableThis.getTableAttrs.tableAttrsArr"
               :key="indexRow"
          >
            <div v-for="(el,index) in item" :key="index">
              {{ el.text }} &nbsp;
              <a-switch
                  checked-children="开"
                  un-checked-children="关"
                  :checked="el.value"
                  @change="(checked,e)=>setTableAttr(checked,e,el.key)"
              />
            </div>
          </div>
        </div>
      </div>
    </a-dropdown>
    <!--高级筛选-->
    <a-dropdown :visible="tableVisible.filterVisible">
      <ant-button
          iconEnable
          title="高级筛选"
          v-show="advancedFilter"
          type="default"
          icon="filter"
          @click="()=>{this.tableVisible.filterVisible=!this.tableVisible.filterVisible}"
          :cclass="{'c-button-active':hasFilterValidData}"
      ></ant-button>
      <div ref="cParamsAttr" slot="overlay" class="c-params-attr">
        <div class="c-params-attr-filter">
          <div class="c-params-attr-title">高级筛选
            <div class="c-params-attr-title-close" @click="()=>{this.tableVisible.filterVisible=false}">
              <a-icon type="close"/>
            </div>
          </div>
          <div class="c-params-attr-desc">已选择 <span class="c-params-attr-desc-num">{{ filterArr.length }}</span>
            个筛选条件
          </div>
          <div class="c-params-attr-condition" v-for="(item,index) in filterArr" :key="index">
            <c-row style="width:100%;margin:0px;">
              <c-col :span="6">
                <a-select :dropdownMatchSelectWidth="false" v-model="item[0]" placeholder="字段"
                          style="width:100%;padding-right:8px;"
                >
                  <a-select-option v-for="(el,Selkey) of getTableThis.getTabTitleArr" :key="Selkey" :value="el.field">
                    {{ el.title }}
                  </a-select-option>
                </a-select>
              </c-col>
              <c-col :span="6">
                <a-select :dropdownMatchSelectWidth="false" v-model="item[1]" placeholder="运算符"
                          style="width:100%;padding-right:8px;"
                >
                  <a-select-option v-for="(el,Selkey) of operatorArr" :key="Selkey" :value="el.value">{{
                      el.text
                    }}
                  </a-select-option>
                </a-select>
              </c-col>
              <c-col :span="8">
                <a-input v-model="item[2]" placeholder="过滤条件" allowClear></a-input>
              </c-col>
              <c-col :span="4" class="c-params-attr-condition-button">
                <ant-button iconEnable type="primary" @click="filterConditionDelete(index)" :align="null">删除</ant-button>
              </c-col>
            </c-row>
          </div>
          <div class="c-params-attr-condition-add">
            <ant-button iconEnable icon="plus" style="margin-left:0px;" @click="filterConditionAdd" type="default">
              添加条件组
            </ant-button>
            <ant-button iconEnable @click="filterConditionReset" type="default">重置</ant-button>
          </div>
          <div class="c-params-attr-footer">
            <ant-button iconEnable @click="()=>{this.tableVisible.filterVisible=false}" type="default">取消</ant-button>
            <ant-button iconEnable @click="filterCondition" :align="null">筛选</ant-button>
          </div>
        </div>
      </div>
    </a-dropdown>
    <!--隐藏/显示列-->
    <a-dropdown :visible="tableVisible.settingVisible">
      <ant-button iconEnable title="隐藏/显示列" icon="setting" type="default"
                @click="()=>{this.tableVisible.settingVisible=true}"
      ></ant-button>
      <a-menu slot="overlay" @mouseleave="()=>{this.tableVisible.settingVisible=false}">
        <a-menu-item v-for="(item,index) of getTableThis.visibleTabTitle.arr" :key="index">
          <a-checkbox
              :value="item.title"
              :checked="getTableThis.visibleTabTitle.visible.find(el=>el===item.title)?true:false"
              @change="hideColumnChange"
          >{{ item.title }}
          </a-checkbox>
        </a-menu-item>
      </a-menu>
    </a-dropdown>
  </div>
</template>

<script>
import moment from 'moment'
import './css/table.less'
import antButton from '../Button/AntButton.vue'
const operatorArr = [
  { value: '0', text: '等于' },
  { value: '1', text: '不等于' },
  { value: '2', text: '大于' },
  { value: '3', text: '大于等于' },
  { value: '4', text: '小于' },
  { value: '5', text: '小于等于' },
  { value: '6', text: '包含' },
  { value: '7', text: '不包含' }
]
export default {
  name: 'AntTableSettingTool',
  components:{
    antButton
  },
  props: {
    // 是否显示固定列，隐藏/显示列设置按钮
    tableShowSetting: {
      type: Boolean, default: true
    },
    // Excel导出 默认不开启
    excelDownLoad: {
      type: Boolean,
      default: false
    },
    // Excel导出选中数据 默认不开启
    excelDownLoadSelected: {
      type: Boolean,
      default: false
    },
    // 高级筛选 默认开启
    advancedFilter: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      visible: false, // 按钮组是否加载
      tableVisible: {
        settingVisible: false, // 展示、隐藏列表是否显示
        attrVisible: false, // 表格属性
        filterVisible: false// 高级过滤
      },
      // 运算符
      operatorArr: operatorArr,
      // 高级过滤器
      filterArr: [],
      tableThis: {} // 表格作用域
    }
  },
  computed: {
    // 获取表格作用域 - 代理作用
    getTableThis() {
      return this.tableThis
    },
    // 获取过滤器中是否存在有效数据
    hasFilterValidData() {
      let flag = false
      for (let i = 0; i < this.filterArr.length; i++) {
        const el = this.filterArr[i]
        const key = el[0]
        const con = el[1]
        if (key && con) {
          flag = true
          break
        }
      }
      return flag
    }
  },
  methods: {
    // 按钮组展示 - 需和表格作用域关联
    showButtons(tableThis) {
      if (!this.tableThis) {
        this.$message.warning('请设置关联表格作用域！')
        return
      }
      this.tableThis = tableThis
      this.visible = true
    },
    /**
     * Excel导出
     * @returns {Promise<void>}
     */
    async exportExcel() {
      const allData = await this.getAllTableDataAfterFilter()
      if (allData) {
        this.getTableThis.exportExcel(allData)
      } else {
        this.$message.warning('数据获取失败，请联系管理员！')
      }
    },
    /**
     * Excel导出选中数据
     * @returns {Promise<void>}
     */
    async exportExcelSelected() {
      const selectedData = this.getTableThis.getSelected()
      if (selectedData.length === 0) {
        this.$message.warning('请选择数据！')
        return
      }
      const allData = selectedData
      if (allData) {
        this.getTableThis.exportExcelSelected(allData)
      } else {
        this.$message.warning('数据获取失败，请联系管理员！')
      }
    },
    /**
     * 设置表格属性全局缓存
     * @param checked
     * @param e
     * @param key
     */
    setTableAttr(checked, e, key) {
      this.getTableThis.setTableAttr(checked, e, key)
    },
    /**
     * 标题字段是否显示
     * @param e
     */
    hideColumnChange(e) {
      this.getTableThis.hideColumnChange(e)
    },
    /**
     * 高级过滤器新增过滤条件
     */
    filterConditionAdd() {
      this.filterArr.push([undefined, undefined, ''])
    },
    /**
     * 高级过滤器删除过滤条件
     * @param index
     */
    filterConditionDelete(index) {
      this.filterArr = this.filterArr.filter((el, num) => num !== index)
    },
    /**
     * 筛选重置
     */
    filterConditionReset() {
      this.filterArr = []
      this.getTableThis.reload(null)
    },
    /**
     * 获取筛选后的所有数据
     * @returns {Promise<*|*[]>}
     */
    async getAllTableDataAfterFilter() {
      let allData = []
      const params = { ...this.getTableThis.currentParam, pageNum: 1, pageSize: -1 }
      const res = await this.$getAction(this.getTableThis.url, params)
      if (res.rows) {
        allData = res.rows
        if (this.getTableThis.loadBefore) {
          this.getTableThis.loadBefore(allData)
        }
        // 2.所有数据进行筛选-所有条件 均需满足
        // 2.1.筛选条件搜集 - 排除undefined
        const condition = new Map()
        this.filterArr.forEach(el => {
          const key = el[0]
          const con = el[1]
          if (key && con) {
            let obj = [el]
            if (condition.get(key)) {
              obj = [...condition.get(key), el]
            }
            condition.set(key, obj)
          }
        })
        // 2.2.筛选
        for (const key of condition.keys()) {
          const arr = condition.get(key)
          // 2.2.1.对应字段单元格格式化
          const fieldInfo = this.getTableThis.getTabTitleArr.find(el => el.field === key)
          // 2.2.2.获取字段指定的筛选比较类型（String、Number、Date）
          const fieldType = fieldInfo.advancedFilter && fieldInfo.advancedFilter.type ? fieldInfo.advancedFilter.type : ''
          const format = (el) => {
            const value = this.getTableThis.formatExcelCellValue(fieldInfo, el)
            return value || ''
          }
          // 2.2.2.批量筛选
          arr.forEach(el => {
            const operator = el[1]
            const value = el[2]
            if (operator === '0') { // 全等于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) === parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) === parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '0'))
              } else {
                allData = allData.filter(item => format(item) === value)
              }
            } else if (operator === '1') { // 不等于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) !== parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) !== parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '5'))
              } else {
                allData = allData.filter(item => format(item) !== value)
              }
            } else if (operator === '2') { // 大于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) > parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) > parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '1'))
              } else {
                allData = allData.filter(item => format(item) > value)
              }
            } else if (operator === '3') { // 大于等于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) >= parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) >= parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '2'))
              } else {
                allData = allData.filter(item => format(item) >= value)
              }
            } else if (operator === '4') { // 小于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) < parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) < parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '3'))
              } else {
                allData = allData.filter(item => format(item) < value)
              }
            } else if (operator === '5') { // 小于等于
              if (fieldType === 'int') {
                allData = allData.filter(item => parseInt(format(item)) <= parseInt(value))
              } else if (fieldType === 'float') {
                allData = allData.filter(item => parseFloat(format(item)) <= parseFloat(value))
              } else if (fieldType === 'date') {
                allData = allData.filter(item => this.compareDate(format(item), value, '4'))
              } else {
                allData = allData.filter(item => format(item) <= value)
              }
            } else if (operator === '6') { // 包含
              allData = allData.filter(item => format(item).indexOf(value) > -1)
            } else if (operator === '7') { // 不包含
              allData = allData.filter(item => format(item).indexOf(value) === -1)
            }
          })
        }
        return allData
      }
    },
    /**
     * 获取所有数据并筛选
     * @returns {Promise<void>}
     */
    async filterCondition() {
      this.tableVisible.filterVisible = false
      // 1.加载所有数据
      if (this.filterArr.length === 0) {
        this.getTableThis.reload(null)
        return
      }
      if (!this.getTableThis.url) {
        this.$message.warning('高级过滤需依赖url')
        return
      }
      const allData = await this.getAllTableDataAfterFilter()
      // 2.3.将符合条件数据设置为表格数据 - 并执行排序和基本过滤规则
      let tableData = []
      const startNum = (this.getTableThis.pageNum - 1) * this.getTableThis.pageSize
      const endNum = this.getTableThis.pageNum * this.getTableThis.pageSize
      if (allData.length > endNum) {
        tableData = allData.slice(startNum, endNum)
      } else if (allData.length > startNum && allData.length < endNum) {
        tableData = allData.slice(startNum)
      }
      this.getTableThis.setTableData(tableData, allData.length)
      this.getTableThis.sortOrFilterRollback()
    },
    /**
     * 时间比较
     * @param date1
     * @param date2
     * @param type
     * @returns {*|boolean}
     */
    compareDate(date1, date2, type) {
      if ((!date1 || date1 === '') && date2 === '') {
        return true
      } else if (date1 && date2 && date1.length > 0 && date2.length > 0) {
        const format = 'YYYY-MM-DD HH:mm:ss'
        const mdate1 = moment(date1, format)
        const mdate2 = moment(date2, format)
        if (type === '0') {
          return mdate1.isSame(mdate2, 'date')
        } else if (type === '1') {
          return mdate1.diff(mdate2, 'seconds') > 0
        } else if (type === '2') {
          return mdate1.diff(mdate2, 'seconds') >= 0
        } else if (type === '3') {
          return mdate1.diff(mdate2, 'seconds') < 0
        } else if (type === '4') {
          return mdate1.diff(mdate2, 'seconds') <= 0
        } else if (type === '5') { // 不等于
          return !mdate1.isSame(mdate2, 'date')
        }
      }
    }
  }
}
</script>

<style lang="less" scoped>
.c-params {
  .ant-btn {
    margin: 0px 16px 0px 0px;
  }

  .ant-btn:last-child {
    margin: 0px 0px 0px 0px;
  }
}
</style>
